#include "dominion.h"
#include "dominion_helpers.h"
#include <stdio.h>
#include <stdlib.h>
#include <glib.h>
#include "card_data.h"
#include <stdbool.h>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
#include <string.h>
#include <assert.h>
#include "utilities.h"
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

gsl_rng *rng;

struct gameState *startup()
// temporarily set config manually--needs to read in from command line for numplayers, etc
{
    unsigned int gslRandomSeed = 1;
    read(open("/dev/urandom", O_RDONLY), &gslRandomSeed, sizeof(gslRandomSeed));
    rng = rng_setup(gslRandomSeed);

gslRandomSeed = 17; // ******************

    printf("gslRandomSeed: %u\n", gslRandomSeed);

    const int minPlayers = 2;
    const int maxPlayers = 4;
    int numPlayers = randomRange(minPlayers, maxPlayers, rng);
    numPlayers = 3;
    printf("Players: %i\n", numPlayers);

    // int kc[10];
    // enum CARD *kingdomCards = (enum CARD *)kc;
    // chooseKingdomCards(kingdomCards, rng);
    int kc[] = {gardens, mine, remodel, smithy, village, baron, great_hall, minion, steward, tribute};
    printf("Kingdom cards: %s, %s, %s, %s, %s, %s, %s, %s, %s, %s\n",
              cards[kc[0]].name, cards[kc[1]].name, cards[kc[2]].name, cards[kc[3]].name, cards[kc[4]].name,
              cards[kc[5]].name, cards[kc[6]].name, cards[kc[7]].name, cards[kc[8]].name, cards[kc[9]].name );

    unsigned int randomSeed = gsl_rng_get(rng);
    randomSeed = 4;
    printf("randomSeed: %u\n", randomSeed);

    struct gameState *state = newGame();
    if (state == NULL)
    {
        g_critical("Failed to create new game");
    }
    initializeGame(numPlayers, kc, randomSeed, state);
    printf("Game initialized\n");
    return state;
}

bool isActionCard(enum CARD c)
{
    if (!(c >= curse && c <= treasure_map))
    {
        g_debug("**** c = %i\n", c);
    }
    assert(c >= curse && c <= treasure_map);
    return cards[c].action;
}

bool isTreasureCard(enum CARD c)
{
    return cards[c].treasure;
}

bool isVictoryCard(enum CARD c)
{
    return cards[c].victory;
}

bool anyActionCards(struct gameState *state)
{
    bool res = false;
    for (int i = 0; i < numHandCards(state); i++)
    {
        assert(handCard(i, state) >= 0);
        if (isActionCard(handCard(i, state)))
        {
            res = true;
            break;
        }
    }
    return res;
}




int playFirstActionCard(struct gameState *state)
// play the first action card in players hand
// assumes that there is an action card in hand
{
    int pos = 0;

    while (!isActionCard(handCard(++pos, state)) && pos < numHandCards(state))
    {}

    // ****** TODO set choices appropriately ******
    int choice1 = 0;
    int choice2 = 0;
    int choice3 = 0;

    enum CARD card = handCard(pos, state);
    setChoices(&choice1, &choice2, &choice3, card, state, rng);

    printf("Action card played: %s\n", cards[card].name);
    printf("Choices: %i, %i, %i\n", choice1, choice2, choice3);

    return playCard(pos, choice1, choice2, choice3, state);

}




bool anyTreasureCards(struct gameState *state)
{
    bool res = false;
    for (int i = 0; i < numHandCards(state); i++)
    {
        if (isTreasureCard(handCard(i, state)))
        {
            res = true;
            break;
        }
    }
    return res;
}


void showHand(struct gameState *state)
{
    int player = whoseTurn(state);
    printf("Player %i\'s hand\n", player);
    for (int i = 0; i < numHandCards(state); i++)
    {
        printf("%i:\t%s\n", i, cards[handCard(i, state)].name);
    }
    printf("\nActions: %i    Buys: %i     Coins: %i\n",
           state->numActions, state->numBuys, state->coins);
}

bool buySomething(struct gameState *state)
{
    int coins = state->coins;
    // bool success = false;
    for (int target_cost = coins; target_cost >= 0; target_cost--)
    {
        for (enum CARD c = curse; c <= treasure_map; c++)
        {
            if (cards[c].cost == target_cost && supplyCount(c, state) > 0)
            {
                if (!buyCard(c, state));
                printf("Bought: %s\n", cards[c].name);
                return true;
            }
        }
    }

    return false;
}

int main (int argv, char **argc)
{
    printf("Game started\n");

    struct gameState *state = startup();
    int turn = 0;

    // initialize sets starting player to 0, only draws cards for this player

    while (!isGameOver(state))
    {
        if (whoseTurn(state) == 0)
        {
            printf("\n\n-*-*-*- Turn %i -*-*-*-\n\n", turn);
        }
        showHand(state);


        // ACTION
        while (anyActionCards(state) && state->numActions > 0)
        {
            if (playFirstActionCard(state) == -1)
            {
                (printf("Action card play failed\n"));
                break;
            }
        }



        // BUY

        int coins = state->coins;
        printf("%i coins\n", coins);

        while (state->numBuys > 0)
        {
            buySomething(state);
        }


        // CLEANUP

        endTurn(state);
        if (whoseTurn(state) == 0)
        {
            turn ++;
        }
    }
    printf("Game over\n");

    int players[MAX_PLAYERS];
    getWinners(players, state);
    printf("Winners: ");

    for (int p = 0; p < state->numPlayers; p++)
    {
        if (players[p] == 1)
        {
            printf("player %i   score: %i\n", p, scoreFor(p, state));
        }
    }
    printf("\n");




    exit(EXIT_SUCCESS);

}